package com.sample.springbatch.job.listener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.stereotype.Component;
import org.springframework.util.SerializationUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;

/**
 * map实现的作业执行追踪器
 * @author zwg
 * @date 2017/11/15.
 */
@Component
public class MapExecutionTracker {

    public static final Logger logger = LoggerFactory.getLogger(MapExecutionTracker.class);

    /** JOB执行信息内存保存数据的最大数量 */
    private static final Long JOB_EXECUTION_MAX_COUNT = 3000L;
    /** STEP执行信息内存保存数据的最大数量 */
    private static final Long STEP_EXECUTION_MAX_COUNT = 3000L;
    /**
     * job 执行信息存储
     */
    private Map<Long, JobExecution> jobExecutionMap = new ConcurrentSkipListMap<>();

    /**
     * step 执行信息存储
     */
    private Map<Long, StepExecution> stepExecutionMap = new ConcurrentSkipListMap<>();

    /**
     * 复制作业执行对象
     * @param original
     * @return
     */
    private static JobExecution copyJobExecution(JobExecution original) {
        return (JobExecution) SerializationUtils.deserialize(SerializationUtils.serialize(original));
    }

    /**
     * 保存作业执行对象到内存  最大保存 @seeJOB_EXECUTION_MAX_COUNT 数量
     * @param jobExecution
     */
    public void saveJobExecution(JobExecution jobExecution) {
        if(jobExecution==null){
            return;
        }
        if(jobExecution.getId()==null || jobExecution.getId()<1){
            logger.error("jobExecution id error {}",jobExecution);
            return;
        }
        try{
            //包含最大数量的ID 先删除
            Long removeId = jobExecution.getId()-JOB_EXECUTION_MAX_COUNT;
            if(removeId>0 && jobExecutionMap.containsKey(removeId)){
                jobExecutionMap.remove(removeId);
                //JobExecution old = jobExecutionMap.remove(removeId);
                //logger.info("jobExecutionMap remove JobExecution {}",old);
            }

            //如果已经存在则替换，否则添加
            if(jobExecutionMap.containsKey(jobExecution.getId())){
                jobExecutionMap.replace(jobExecution.getId(), copyJobExecution(jobExecution));
            }else{
                jobExecutionMap.put(jobExecution.getId(), copyJobExecution(jobExecution));
            }
        }catch (Exception e){
            logger.error("saveJobExecution",e);
        }
    }

    /**
     * 获取作业执行信息
     * @param id
     * @return
     */
    public JobExecution getJobExecutionById(Long id){
        if(jobExecutionMap!=null && jobExecutionMap.containsKey(id)){
            return copyJobExecution(jobExecutionMap.get(id));
        }else{
            return null;
        }
    }


    /**
     * 保存STEP执行对象到内存
     * @param original
     * @return
     */
    private static StepExecution copyStepExecution(StepExecution original) {
        return (StepExecution) SerializationUtils.deserialize(SerializationUtils.serialize(original));
    }

    /**
     * 保存STEP执行对象到内存  最大保存 @see STEP_EXECUTION_MAX_COUNT 数量
     * @param stepExecution
     */
    public void saveStepExecution(StepExecution stepExecution) {
        if(stepExecution==null){
            return;
        }
        if(stepExecution.getId()==null || stepExecution.getId()<1){
            logger.error("stepExecution id error {}",stepExecution);
            return;
        }
        try{
            //包含最大数量的ID 先删除
            Long removeId = stepExecution.getId()-STEP_EXECUTION_MAX_COUNT;
            if(removeId>0 && stepExecutionMap.containsKey(removeId)){
                stepExecutionMap.remove(removeId);
                //StepExecution old = stepExecutionMap.remove(removeId);
                //logger.info("stepExecutionMap remove StepExecution {}",old);

            }

            //如果已经存在则替换，否则添加
            if(stepExecutionMap.containsKey(stepExecution.getId())){
                stepExecutionMap.replace(stepExecution.getId(), copyStepExecution(stepExecution));
            }else{
                stepExecutionMap.put(stepExecution.getId(), copyStepExecution(stepExecution));
            }
        }catch (Exception e){
            logger.error("saveStepExecution",e);
        }

    }


    /**
     * 获取step执行信息
     * @param id
     * @return
     */
    public StepExecution getStepExecutionById(Long id){
        if(stepExecutionMap!=null && stepExecutionMap.containsKey(id)){
            return copyStepExecution(stepExecutionMap.get(id));
        }else{
            return null;
        }
    }


    public void showJobExecutionMap(Long jobExecutionId){
        if(jobExecutionId==null || !jobExecutionMap.containsKey(jobExecutionId)){
            for (Long id:jobExecutionMap.keySet()) {
                logger.info(jobExecutionMap.get(id).toString());
            }
        }else{
            logger.info(jobExecutionMap.get(jobExecutionId).toString());
        }
    }


    public void showStepExecutionMap(Long stepExecutionId){
        if(stepExecutionId==null || !stepExecutionMap.containsKey(stepExecutionId)){
            for (Long id:stepExecutionMap.keySet()) {
                logger.info(stepExecutionMap.get(id).toString());
            }
        }else{
            logger.info(stepExecutionMap.get(stepExecutionId).toString());
        }
    }


}
